perm filename PMOV[S1,ALS] blob
sn#402194 filedate 1978-12-13 generic text, type C, neo UTF8
COMMENT ā VALID 00002 PAGES
C REC PAGE DESCRIPTION
C00001 00001
C00002 00002 PMOV :
C00009 ENDMK
Cā;
PMOV :
begin (*PMOV*)
(* LCW 2AUG78 Modified by ALS 3Dec78
The strategy for PMOV is to do a BLKMOV if the transfer length is long
enough to justify the BLKMOV overhead,
else if (I1 mod 4)=0 then if (([OPND1] mod 4)=0 and ([OPND2] mod 4)=0)
then do a series of MOVMSs starting with the longest available MOVMS and
proceeding to the short MOVMSs if necessary,
else to do a series of MOVMQs, starting with the longest available MOVMQ
and proceeding to the short MOVMQs if necessary.
This procedure ignores the problem associated with having overlapping
source and destination where the source address is less than the
destination address. In that case, SOPA may destroy the source during
the MOV. However, if the source and destination overlap completely,
then SOPA will not destroy the source. Note that PASCAL and PCode do
not explicitly define the semantics of MOV when the source and
destination incompletely overlap.
*)
if not (STK[TOP-1].DTYPE in [TYPA,TYPM]) or
not (STK[TOP].DTYPE in [TYPA,TYPM]) then
ERROR (WMOV_NEEDS_ADDRS);
if I1 >= BLKMOV_THRESH then
begin (*generate BLKMOV*)
(*make sure that the global zero and CPL are free (error if not)*)
ALLOCGBL (S1GBLZ);
ALLOCRG (S1RCPL);
ALLOCRG (succ(S1RCPL));
ALLOCRG (succ(succ(S1RCPL)));
(* initialize the global zero *)
OP1GBL := S1GBLZ;
ADDR_OPERAND (OPND1, OP1GBL*WORDUNITS);
EMITXOP (XMOV_S_S, OPND1, ZERO_OP);
(*initialize the CPL block descriptor*)
REG_OPERAND (OPNDR1, S1RCPL);
IMM_OPERAND (OPND2, S1GBLZ*WORDUNITS);
EMITXOP (XMOV_S_S, OPNDR1, OPND2);
REG_OPERAND (OPNDR1, succ(S1RCPL));
MOVE_QUANTITY (OPNDR1, TOP-1);
REG_OPERAND (OPNDR1, succ(succ(S1RCPL)));
IMM_OPERAND (OPND2, I1);
EMITXOP (XMOV_S_S, OPNDR1, OPND2);
(*emit the BLKMOV*)
REG_OPERAND (OPNDR1, S1RCPL);
GET_ADDRESS (OPND2, TOP);
EMITXOP (XBLKMOV, OPNDR1, OPND2);
(*free the global zero and CPL registers*)
FREEGBL_S (S1GBLZ);
FREERG_S (S1RCPL);
FREERG_S (succ(S1RCPL));
FREERG_S (succ(succ(S1RCPL)));
end (*generate BLKMOV*)
else
begin (*generate MOVMSs or MOVMQs after test*)
if ((I1 mod 4)=0 and
ZZZZZZZZ Code to see if starts are on word boundaries ZZZZZZZZ )
then
begin (*generate MOVMS*)
XFER_CNT := I1/4;
while XFER_CNT >= 32 do
begin
GET_ADDRESS (OPND1, TOP-1);
GET_ADDRESS (OPND2, TOP);
EMITXOP (XMOVMS_32, OPND1, OPND2);
XFER_CNT := XFER_CNT - 32;
if XFER_CNT > 0 then
begin
INCREMENT_DATUM (TOP-1, 128);
INCREMENT_DATUM (TOP, 128);
end;
end;
if XFER_CNT > 0 then
begin
GET_ADDRESS (OPND1, TOP-1);
GET_ADDRESS (OPND2, TOP);
EMITXOP (MOVMS_N[XFER_CNT], OPND1, OPND2);
end;
end (*generate MOVMS*)
else
begin (*generate MOVMQ*)
XFER_CNT := I1;
while XFER_CNT >= 128 do
begin
GET_ADDRESS (OPND1, TOP-1);
GET_ADDRESS (OPND2, TOP);
EMITXOP (XMOVMQ_128, OPND1, OPND2);
XFER_CNT := XFER_CNT - 128;
if XFER_CNT > 0 then
begin
INCREMENT_DATUM (TOP-1, 128);
INCREMENT_DATUM (TOP, 128);
end;
end;
if XFER_CNT >= 64 then
begin
GET_ADDRESS (OPND1, TOP-1);
GET_ADDRESS (OPND2, TOP);
EMITXOP (XMOVMQ_64, OPND1, OPND2);
XFER_CNT := XFER_CNT - 64;
if XFER_CNT > 0 then
begin
INCREMENT_DATUM (TOP-1, 64);
INCREMENT_DATUM (TOP, 64);
end;
end;
if XFER_CNT >= 32 then
begin
GET_ADDRESS (OPND1, TOP-1);
GET_ADDRESS (OPND2, TOP);
EMITXOP (XMOVMQ_32, OPND1, OPND2);
XFER_CNT := XFER_CNT - 32;
if XFER_CNT > 0 then
begin
INCREMENT_DATUM (TOP-1, 32);
INCREMENT_DATUM (TOP, 32);
end;
end;
if XFER_CNT > 0 then
begin
GET_ADDRESS (OPND1, TOP-1);
GET_ADDRESS (OPND2, TOP);
EMITXOP (MOVMQ_N[XFER_CNT], OPND1, OPND2);
end;
end (*generate MOVMQ*)
end (*generate MOVMS or MOVMQ);
FREEDATUMREGS (TOP);
POPTOP;
FREEDATUMREGS (TOP);
POPTOP;
end (*PMOV*);